#pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include "Session.hpp"

const std::string HTTPSEP = "\r\n";
const std::string HOMEPAGE = "index.html";
const std::string WWWROOT = "./wwwRoot";

class HttpRequest
{
public:
    HttpRequest() : _req_blank(HTTPSEP), _path(WWWROOT)
    {}

    ~HttpRequest(){}

    // line: 输出型参数
    bool GetLine(std::string& str, std::string* line)
    {
        auto pos = str.find(HTTPSEP);
        if (pos == std::string::npos) 
            return false;

        *line = str.substr(0, pos);
        str.erase(0, pos + HTTPSEP.size());
        return true;
    }

    // 反序列化
    bool Deserialize(std::string& request) 
    {
        std::string line;
        if(!GetLine(request, &line))
            return false;
        
        _req_line = line;
        while(true)
        {
            bool flag = GetLine(request, &line);
            if(flag && line.empty()) {
                _req_content = request;
                break;
            } else if (flag && !line.empty()) {
                _req_header.push_back(line);
            } else {
                break;
            }
        }

        return true;
    }

    // 解析请求行
    void ParseReqLine()
    {
        std::stringstream ss(_req_line);
        ss >> _method >> _url >> _http_version;

        if(_url == "/") {
            _path += _url;
            _path += HOMEPAGE;
        } else {
            _path += _url;
        }
    }

    void ParseSuffix() 
    {
        auto pos = _path.rfind(".");
        if(pos == std::string::npos)
            _suffix = ".html";
        else
            _suffix = _path.substr(pos);    
    }

    void Parse()
    {
        // 解析请求行
        ParseReqLine();
        // 解析后缀 wwwroot/A/B/C.html -> .html
        ParseSuffix();
    }

    // 输出http请求信息
    void DebugHttp()
    {
        std::cout << "_req_line: " << _req_line << std::endl;
        for (auto &line : _req_header)
        {
            std::cout << "---> " << line << std::endl;
        }
        std::cout << "_req_blank: " << _req_blank << std::endl;
        std::cout << "_req_content: " << _req_content << std::endl;

        std::cout << "Method: " << _method << std::endl;
        std::cout << "url: " << _url << std::endl;
        std::cout << "http_version: " << _http_version << std::endl;
    }

    // 获取文件内容
    std::string GetFileContent(const std::string& path) 
    {
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
            return "";
 
        in.seekg(0, in.end); // 设置文件流的读取位置
        int fSize = in.tellg(); // 获取文件大小
        in.seekg(0, in.beg);

        std::string content; // 将文件内容读取到content
        content.resize(fSize);
        in.read(&content[0], fSize);

        in.close();

        return content;
    }

    std::string GetFileContent()
    {
        return GetFileContent(_path);
    }

    std::string Get_ERROR_404()
    {
        return GetFileContent("./wwwRoot/404.html");
    }

    std::string Url()
    {
        return _url;
    }

    std::string Path()
    {
        return _path;
    }

    std::string Suffix()
    {
        return _suffix;
    }

private:
    // 报文请求内容
    std::string _req_line;
    std::vector<std::string> _req_header;
    std::string _req_blank;
    std::string _req_content;

    // 解析后
    std::string _method; // GET POST
    std::string _url;      // 请求行中的url
    std::string _http_version; // HTTP/1.1
    std::string _path; // "./wwwRoot"
    std::string _suffix; // 请求资源的后缀
};


const std::string BlankSep = " ";
const std::string LineSep = "\r\n";

class HttpResponse
{
public:
    HttpResponse() : _http_version("HTTP/1.0"), _status_code(200), _status_code_desc("OK"), _resp_blank(LineSep)
    {}
    ~HttpResponse(){}

    void SetCode(int code) 
    {
        _status_code = code;
    }

    void SetCodeDesc(const std::string& desc)
    {
        _status_code_desc = desc;
    }

    void SetHttpVersion(const std::string& version)
    {
        _http_version = version;
    }

    void SetContent(const std::string& content)
    {
        _resp_content = content;
    }

    void AddHeader(const std::string& header)
    {
        _resp_header.push_back(header);
    }

    void MakeStatusLine()
    {
        // HTTP/1.1 200 OK\r\n
        _status_line = _http_version + BlankSep + std::to_string(_status_code) + BlankSep + _status_code_desc + LineSep;
    }

    std::string Serialize()
    {
        std::string resp_str = _status_line;
        for (auto &header : _resp_header)
        {
            // resp_str += header + LineSep;
            resp_str += header;
        }

        resp_str += _resp_blank + _resp_content;

        return resp_str;
    }

private:
    std::string _status_line;
    std::vector<std::string> _resp_header;
    std::string _resp_blank;
    std::string _resp_content;

    std::string _http_version;
    int _status_code;
    std::string _status_code_desc;
};